package com.ll.agent.ASMStudy.Interface;

import com.ll.agent.visitor.MyMethodVisitor;
import com.sun.tools.classfile.Opcode;
import org.objectweb.asm.*;
import org.objectweb.asm.commons.AdviceAdapter;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Random;

/**
 * @description:
 * @author: LiuLei
 * @create: 2024-07-19
 **/
public class ModifyParametersClassAdapter extends ClassVisitor {


    private final String className;

    public ModifyParametersClassAdapter(ClassVisitor classVisitor, String className) {
        super(Opcodes.ASM9, classVisitor);
        this.className = className;
    }

    @Override
    public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
        // superName java/lang/Object
        for (String interfaceName : interfaces){
            System.out.println(interfaceName);
        }
        super.visit(version, access, name, signature, superName, interfaces);
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
        MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
        // 只转换 foo 方法
        if ("say".equals(name)) {
            return new ModifySingleParamAdviceAdapter(Opcodes.ASM9,mv, access, name, descriptor);
        }
        return mv;
    }
    //
    private static class ModifySingleParamAdviceAdapter extends AdviceAdapter {

        protected ModifySingleParamAdviceAdapter(int api, MethodVisitor methodVisitor, int access, String name, String descriptor) {
            super(api, methodVisitor, access, name, descriptor);
        }

        @Override
        protected void onMethodEnter() {
            super.onMethodEnter();
            int customValue = new Random().nextInt();
            System.out.println("自定义参数=" + customValue);
            mv.visitIntInsn(SIPUSH, customValue); // 加载自定义值到操作数栈
            mv.visitVarInsn(ISTORE, 1); // 将结果存回第一个参数的位置
        }

    }

    private static class ModifyParamsAndReturnAdviceAdapter extends AdviceAdapter {
        protected ModifyParamsAndReturnAdviceAdapter(int api, MethodVisitor methodVisitor, int access, String name, String descriptor) {
            super(api, methodVisitor, access, name, descriptor);
        }

        @Override
        protected void onMethodEnter() {
            super.onMethodEnter();
            mv.visitVarInsn(ALOAD, 0);
            mv.visitIntInsn(SIPUSH, 5555); // 修改第一个参数为5555
            mv.visitVarInsn(ISTORE, 1); // 存回第一个参数的位置
        }

        @Override
        protected void onMethodExit(int opcode) {
            if (opcode == IRETURN) {
                mv.visitInsn(POP); // 弹出原始返回值
                mv.visitIntInsn(SIPUSH, 9999); // 插入新的返回值9999
            }
        }
    }


    public static void main(String[] args) throws IOException {

        String[] classNames = {"com.ll.agent.ASMStudy.Interface.ImplOne".replace(".","/"), "com.ll.agent.ASMStudy.Interface.ImplTwo".replace(".","/"),"com.ll.agent.ASMStudy.Interface.ImplOneOne".replace(".","/")};
        for (String className: classNames){
            System.out.println(className);
            ClassReader classReader = new ClassReader(className);
            ClassWriter classWriter = new ClassWriter(classReader, ClassWriter.COMPUTE_MAXS);
            ModifyParametersClassAdapter modifyParametersClassAdapter = new ModifyParametersClassAdapter(classWriter, className);
            classReader.accept(modifyParametersClassAdapter, ClassReader.EXPAND_FRAMES);

            byte[] modifiedClass = classWriter.toByteArray();
            try (FileOutputStream fos = new FileOutputStream("/Users/liulei/my/instruStudy/agent/src/main/java/" + className.replace('.', '/') + ".class")) {
                fos.write(modifiedClass);
            }
            System.out.println("Class transformation complete.");
        }


    }



}
